#pragma once
#include "Sem.hpp"
#include "Mutex.hpp"
#include <vector>

static const int gcap = 8;

template <typename T>
class Ringqueue
{
public:
    Ringqueue(int cap = gcap)
        : _v(cap), _cap(cap), _p_step(0), _s_step(0), _blank_sem(cap), _data_sem(cap)
    {
    }

    void Enqueue(T &in)
    {
        _blank_sem.P();
        {
            LockGuard lockguard(_p_mutex);
            _v[_p_step] = in;
            _p_step++;
            _p_step %= _cap;
        }
        _data_sem.V();
    }

    T Pop()
    {
        T data;
        _data_sem.P();
        {
            LockGuard lockguard(_s_mutex);
            data = _v[_s_step];
            _s_step++;
            _s_step %= _cap;
        }
        _blank_sem.V();
        return data;
    }

    ~Ringqueue()
    {
    }

private:
    // 生产者
    Sem _blank_sem;
    int _p_step;
    // 消费者
    Sem _data_sem;
    int _s_step;
    // 存储循环体
    vector<T> _v;
    int _cap;
    // 两把锁
    Mutex _p_mutex;
    Mutex _s_mutex;
};